﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using D20.Entities.Items;

namespace D20.Entities.Characters
{
    /// <summary>
    /// A living entity.
    /// </summary>
    public abstract class Creature : Entity
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Creature"/> class.
        /// </summary>
        protected Creature()
            : base()
        {
            PersonalInventory = new Inventory();
            Minions = new List<Creature>(0);
            SkillSet = new SkillSet();
            Attitude = new Attitude();
            Abilities = new Abilities();
            NextLevelUp = 1000;
        }
        /// <summary>
        /// Gets the personal inventory.
        /// </summary>
        /// <value>The personal inventory.</value>
        public Inventory PersonalInventory { get; private set; }
        /// <summary>
        /// Gets the minions of this creature.
        /// </summary>
        /// <value>The minions.</value>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public List<Creature> Minions { get; private set; }

        /// <summary>
        /// Gets the skill set.
        /// </summary>
        /// <value>The skill set.</value>
        public SkillSet SkillSet { get; private set; }
        /// <summary>
        /// Gets or sets the level.
        /// </summary>
        /// <value>The level.</value>
        [CLSCompliant(false)]
        public uint Level { get; private set; }
        /// <summary>
        /// Gets or sets the experience.
        /// </summary>
        /// <value>The experience.</value>
        [CLSCompliant(false)]
        public ulong Experience { get; private set; }
        /// <summary>
        /// Gets or sets the next level up.
        /// </summary>
        /// <value>The next level up.</value>
        [CLSCompliant(false)]
        public ulong NextLevelUp { get; private set; }
        /// <summary>
        /// Adds the experience, and levels up if neccessary.
        /// </summary>
        /// <param name="experience">The experience.</param>
        /// <returns></returns>
        [CLSCompliant(false)]
        public bool AddExperience(ulong experience)
        {
            Experience += experience;
            OnGainedExperienceEventHandler gainedExperienceHandler = OnGainedExperience;
            if (gainedExperienceHandler != null)
            {
                gainedExperienceHandler(new GainedExperienceEventArgs(experience, this));
            }
            if (Experience >= NextLevelUp)
            {
                Level++;
                NextLevelUp += Level * 1000;
                OnLevelUpEventHandler levelUpHandler = OnLevelUp;
                if (levelUpHandler != null)
                {
                    levelUpHandler(new LevelUpEventArgs(experience, Level, this));
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Computes the experience needed to level up.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <returns></returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        private static ulong ComputeExperienceNeededToLevelUp(uint level)
        {
            ulong experienceNeeded = 0;
            for (uint i = 0; i < level; i++)
            {
                experienceNeeded += level * 1000;
            }
            return experienceNeeded;
        }
        /// <summary>
        /// Gets or sets the abilities.
        /// </summary>
        /// <value>The abilities.</value>
        public Abilities Abilities { get; private set; }
        /// <summary>
        /// Gets the attitude.
        /// </summary>
        /// <value>The attitude.</value>
        public Attitude Attitude { get; private set; }
        #region Eventhandlers

        /// <summary>
        /// Occurs on level up.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly")]
        public event OnLevelUpEventHandler OnLevelUp;
        
        /// <summary>
        /// Occurs when a creature gains experience.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly")]
        public event OnGainedExperienceEventHandler OnGainedExperience;

        #endregion
    }
    #region Events/delegates

    #region Level up
    /// <summary>
    /// Event arguments for the <see cref="LevelUpEventArgs"/> delegate.
    /// </summary>
    public class LevelUpEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LevelUpEventArgs"/> class.
        /// </summary>
        [CLSCompliant(false)]
        public LevelUpEventArgs(ulong addedExperience, uint newLevel, Entity target)
        {
            AddedExperience = addedExperience;
            NewLevel = newLevel;
            Target = target;
        }
        /// <summary>
        /// Gets the added experience.
        /// </summary>
        /// <value>The added experience.</value>
        [CLSCompliant(false)]
        public ulong AddedExperience { get; private set; }
        /// <summary>
        /// Gets the new level.
        /// </summary>
        /// <value>The new level.</value>
        [CLSCompliant(false)]
        public uint NewLevel { get; private set; }
        /// <summary>
        /// Gets the target.
        /// </summary>
        /// <value>The target.</value>
        public Entity Target { get; private set; }
    }
    /// <summary>
    /// A delegate that is called when a creature levels up.
    /// </summary>
    public delegate void OnLevelUpEventHandler(LevelUpEventArgs e);
    #endregion

    #region Gained experience
    /// <summary>
    /// Event arguments for the <see cref="GainedExperienceEventArgs"/> delegate.
    /// </summary>
    public class GainedExperienceEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GainedExperienceEventArgs"/> class.
        /// </summary>
        [CLSCompliant(false)]
        public GainedExperienceEventArgs(ulong addedExperience, Entity target)
        {
            AddedExperience = addedExperience;
            Target = target;
        }
        /// <summary>
        /// Gets the added experience.
        /// </summary>
        /// <value>The added experience.</value>
        [CLSCompliant(false)]
        public ulong AddedExperience { get; private set; }
        /// <summary>
        /// Gets the target.
        /// </summary>
        /// <value>The target.</value>
        public Entity Target { get; private set; }
    }
    /// <summary>
    /// A delegate that is called when a creature gains experience.
    /// </summary>
    public delegate void OnGainedExperienceEventHandler(GainedExperienceEventArgs e);
    #endregion

    #endregion
}
